package importexport;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.activation.MimetypesFileTypeMap;

import main.Main;

import database.Database;

public class Export {
	
	private static Vector<objects.Contact> contacts = new Vector<objects.Contact>();
	private static Vector<objects.Course> courses = new Vector<objects.Course>();
	private static Vector<objects.Event> events = new Vector<objects.Event>();
	private static Vector<objects.Exam> exams = new Vector<objects.Exam>();
	private static Vector<objects.Lesson> lessons = new Vector<objects.Lesson>();
	private static Vector<objects.Project> projects = new Vector<objects.Project>();
	private static Vector<objects.Student> students = new Vector<objects.Student>();
	private static Vector<objects.Task> tasks = new Vector<objects.Task>();
	private static Vector<objects.Teacher> teachers = new Vector<objects.Teacher>();
	
	public static void exportZip(String path, Vector<Object> objects) throws Exception {
		Database db = Main.db;
		for (int i = 0; i < objects.size(); i++) {
			if (objects.get(i) instanceof objects.Teacher) {
				objects.Teacher obj = (objects.Teacher) objects.get(i);
				teachers.add(obj);
			}
			else if (objects.get(i) instanceof objects.Course) {
				objects.Course obj = (objects.Course) objects.get(i);
				courses.add(obj);
			}
			else if (objects.get(i) instanceof objects.Lesson) {
				objects.Lesson obj = (objects.Lesson) objects.get(i);
				lessons.add(obj);
			}
			else if (objects.get(i) instanceof objects.Exam) {
				objects.Exam obj = (objects.Exam) objects.get(i);
				exams.add(obj);
			}
			else if (objects.get(i) instanceof objects.Event) {
				objects.Event obj = (objects.Event) objects.get(i);
				events.add(obj);
			}
			else if (objects.get(i) instanceof objects.Project) {
				objects.Project obj = (objects.Project) objects.get(i);
				projects.add(obj);
			}
			else if (objects.get(i) instanceof objects.Student) {
				objects.Student obj = (objects.Student) objects.get(i);
				students.add(obj);
			}
			else if (objects.get(i) instanceof objects.Task) {
				objects.Task obj = (objects.Task) objects.get(i);
				tasks.add(obj);
			}
			else if (objects.get(i) instanceof objects.Contact) {
				objects.Contact obj = (objects.Contact) objects.get(i);
				contacts.add(obj);
			}
		}
		createFiles(db);
		createZip(path);
		File exportdir = new File("export");
		recursiveDelete(exportdir);
	}
	
	private static void createFiles(Database db) throws Exception {
		File dir = new File("export");
		dir.mkdir();
		if (!dir.exists()) {
			dir.mkdir();
		}
		FileWriter fstream = new FileWriter("export\\export.xml");
        BufferedWriter out = new BufferedWriter(fstream);
        out.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<export>\r\n");
        if (courses.size() > 0) {
        	out.write("<courses>\r\n");
        	for (int i = 0; i < courses.size(); i++) {
        		objects.Course course = courses.get(i);
        		out.write("<course>\r\n");
        		
        		out.write("<name>" + course.getName() + "</name>\r\n");
        		if (!course.getDescription().equals("")) {
        			out.write("<description>" + course.getDescription() + "</description>\r\n");
        		}
        		Vector<objects.Teacher> courseteachers = db.rCTeach.getTeachers(course.getName());
        		if (courseteachers.size() > 0) {
        			out.write("<tutors>\r\n");
        			for (int j = 0; j < courseteachers.size(); j++) {
        				if (courseteachers.get(j).getTitle().contains("Prof")) {
        					out.write("<tutor type=\"professor\">\r\n");
        				}
        				else {
        					out.write("<tutor type=\"assistant\">\r\n");
        				}
        				out.write("<contact>" + courseteachers.get(j).getEmail() + "</contact>\r\n</tutor>\r\n");
        			}
        			out.write("</tutors>\r\n");
        		}
        		Vector<objects.File> coursefiles = db.rCF.getFiles(course.getName());
        		if (coursefiles.size() > 0) {
        			out.write("<files>\r\n");
        			for (int j = 0; j < coursefiles.size(); j++) {
        				File oldfile = new File("files\\" + coursefiles.get(j).getPathname());
        				File newfile = new File("export\\" + oldfile.getName());
        				copyFile(oldfile, newfile);
        				out.write("<file type=" + new MimetypesFileTypeMap().getContentType(newfile) + ">\r\n");
        				out.write("<path>" + oldfile.getName() + "</path>\r\n</file>\r\n");
        			}
        			out.write("</files>\r\n");
        		}
        		
        		out.write("</course>\r\n");
        	}
        	out.write("</courses>\r\n");
        }
        if (projects.size() > 0 | tasks.size() > 0 | exams.size() > 0) {
        	out.write("<projects>\r\n");
        	
        	if (projects.size() > 0) {
        		for (int i = 0; i < projects.size(); i++) {
        			objects.Task task = projects.get(i);
        			out.write("<project>\r\n");
            		out.write("<name>" + task.getName() + "</name>\r\n");
            		objects.Course c = db.rCTask.getCourse(task.getName());
            		if (c != null) {
            			out.write("<course>" + c.getName() + "</course>\r\n");
            		}
            		out.write("<description>" + task.getDescription() + "</description>\r\n");
            		Vector<objects.Event> deadlines = db.rTE.getEvents(task.getName());
            		if (deadlines.size() > 0) {
            			out.write("<deadlines>\r\n");
            			for (int j = 0; j < deadlines.size(); j++) {
            				out.write("<deadline>\r\n");
            				out.write("<description>" + deadlines.get(j).getSummary() + "</description>\r\n");
            				out.write("<dateTime>" + deadlines.get(j).getStart() + "</dateTime>\r\n");
            				out.write("</deadline>\r\n");
            			}
            			out.write("</deadlines>\r\n");
            		}
            		Vector<objects.Student> members = db.rPS.getStudents(task.getName());
            		if (members.size() > 0) {
            			out.write("<members>\r\n");
            			for (int j = 0; j < members.size(); j++) {
            				out.write("<member>\r\n");
            				out.write("<contact>" + members.get(j).getEmail() + "</contact>\r\n");
            				out.write("</member>\r\n");
            			}
            			out.write("</members>\r\n");
            		}
            		Vector<objects.File> taskfiles = db.rTF.getFiles(task.getName());
            		if (taskfiles.size() > 0) {
            			out.write("<files>\r\n");
            			for (int j = 0; j < taskfiles.size(); j++) {
            				File oldfile = new File("files\\" + taskfiles.get(j).getPathname());
            				File newfile = new File("export\\" + oldfile.getName());
            				copyFile(oldfile, newfile);
            				out.write("<file type=" + new MimetypesFileTypeMap().getContentType(newfile) + ">\r\n");
            				out.write("<path>" + oldfile.getName() + "</path>\r\n</file>\r\n");
            			}
            			out.write("</files>\r\n");
            		}
            		out.write("</project>\r\n");
        		}
        	}	
        	if (tasks.size() > 0) {
        		for (int i = 0; i < tasks.size(); i++) {
        			objects.Task task = tasks.get(i);
        			out.write("<project>\r\n");
            		out.write("<name>" + task.getName() + "</name>\r\n");
            		objects.Course c = db.rCTask.getCourse(task.getName());
            		if (c != null) {
            			out.write("<course>" + c.getName() + "</course>\r\n");
            		}
            		out.write("<description>" + task.getDescription() + "</description>\r\n");
            		Vector<objects.Event> deadlines = db.rTE.getEvents(task.getName());
            		if (deadlines.size() > 0) {
            			out.write("<deadlines>\r\n");
            			for (int j = 0; j < deadlines.size(); j++) {
            				out.write("<deadline>\r\n");
            				out.write("<description>" + deadlines.get(j).getSummary() + "</description>\r\n");
            				out.write("<dateTime>" + deadlines.get(j).getStart() + "</dateTime>\r\n");
            				out.write("</deadline>\r\n");
            			}
            			out.write("</deadlines>\r\n");
            		}
            		Vector<objects.Student> members = db.rPS.getStudents(task.getName());
            		if (members.size() > 0) {
            			out.write("<members>\r\n");
            			for (int j = 0; j < members.size(); j++) {
            				out.write("<member>\r\n");
            				out.write("<contact>" + members.get(j).getEmail() + "</contact>\r\n");
            				out.write("</member>\r\n");
            			}
            			out.write("</members>\r\n");
            		}
            		Vector<objects.File> taskfiles = db.rTF.getFiles(task.getName());
            		if (taskfiles.size() > 0) {
            			out.write("<files>\r\n");
            			for (int j = 0; j < taskfiles.size(); j++) {
            				File oldfile = new File("files\\" + taskfiles.get(j).getPathname());
            				File newfile = new File("export\\" + oldfile.getName());
            				copyFile(oldfile, newfile);
            				out.write("<file type=" + new MimetypesFileTypeMap().getContentType(newfile) + ">\r\n");
            				out.write("<path>" + oldfile.getName() + "</path>\r\n</file>\r\n");
            			}
            			out.write("</files>\r\n");
            		}
            		out.write("</project>\r\n");
        		}
        	}
        	if (exams.size() > 0) {
        		for (int i = 0; i < exams.size(); i++) {
        			objects.Task task = exams.get(i);
        			out.write("<project>\r\n");
            		out.write("<name>" + task.getName() + "</name>\r\n");
            		objects.Course c = db.rCTask.getCourse(task.getName());
            		if (c != null) {
            			out.write("<course>" + c.getName() + "</course>\r\n");
            		}
            		out.write("<description>" + task.getDescription() + "</description>\r\n");
            		Vector<objects.Event> deadlines = db.rTE.getEvents(task.getName());
            		if (deadlines.size() > 0) {
            			out.write("<deadlines>\r\n");
            			for (int j = 0; j < deadlines.size(); j++) {
            				out.write("<deadline>\r\n");
            				out.write("<description>" + deadlines.get(j).getSummary() + "</description>\r\n");
            				out.write("<dateTime>" + deadlines.get(j).getStart() + "</dateTime>\r\n");
            				out.write("</deadline>\r\n");
            			}
            			out.write("</deadlines>\r\n");
            		}
            		Vector<objects.Student> members = db.rPS.getStudents(task.getName());
            		if (members.size() > 0) {
            			out.write("<members>\r\n");
            			for (int j = 0; j < members.size(); j++) {
            				out.write("<member>\r\n");
            				out.write("<contact>" + members.get(j).getEmail() + "</contact>\r\n");
            				out.write("</member>\r\n");
            			}
            			out.write("</members>\r\n");
            		}
            		Vector<objects.File> taskfiles = db.rTF.getFiles(task.getName());
            		if (taskfiles.size() > 0) {
            			out.write("<files>\r\n");
            			for (int j = 0; j < taskfiles.size(); j++) {
            				File oldfile = new File("files\\" + taskfiles.get(j).getPathname());
            				File newfile = new File("export\\" + oldfile.getName());
            				copyFile(oldfile, newfile);
            				out.write("<file type=" + new MimetypesFileTypeMap().getContentType(newfile) + ">\r\n");
            				out.write("<path>" + oldfile.getName() + "</path>\r\n</file>\r\n");
            			}
            			out.write("</files>\r\n");
            		}
            		
            		out.write("</project>\r\n");
        		}
        	}
        	out.write("</projects>\r\n");
        }
        if (events.size() > 0 | lessons.size() > 0) {
        	out.write("<calendar>\r\n<file type=\"text/calendar\">schedule.ical</file>\r\n</calendar>\r\n");
        	FileWriter fstream2 = new FileWriter("export\\schedule.ical");
            BufferedWriter calout = new BufferedWriter(fstream2);
            calout.write("BEGIN:VCALENDAR\r\nVERSION:1.0\r\n");
            if (events.size() > 0) {
            	for (int j = 0; j < events.size(); j++) {
            		if (!events.get(j).getIsDeadline().equalsIgnoreCase("true")) {
            			calout.write("BEGIN:VEVENT\r\nDTSTART:" + events.get(j).getStart() + "\r\n");
            			calout.write("DTEND:" + events.get(j).getEnd() + "\r\nSUMMARY:" + events.get(j).getSummary() + "\r\n");
            			if (!events.get(j).getStart().equals(events.get(j).getWarningDate())) {
            				calout.write("BEGIN:VALARM\r\nTRIGGER:" + events.get(j).getWarningDate() + "\r\nEND:VALARM\r\n");
            			}
            			calout.write("END:VEVENT\n");
            		}
            	}
            }
            if (lessons.size() > 0) {
            	for (int j = 0; j < lessons.size(); j++) {
            		if (!lessons.get(j).getIsDeadline().equalsIgnoreCase("true")) {
            			calout.write("BEGIN:VEVENT\r\nDTSTART:" + lessons.get(j).getStart() + "\r\n");
            			calout.write("DTEND:" + lessons.get(j).getEnd() + "\r\nSUMMARY:" + lessons.get(j).getSummary() + "\r\n");
            			if (!lessons.get(j).getStart().equals(lessons.get(j).getWarningDate())) {
            				calout.write("BEGIN:VALARM\r\nTRIGGER:" + lessons.get(j).getWarningDate() + "\r\nEND:VALARM\r\n");
            			}
            			calout.write("END:VEVENT\n");
            		}
            	}
            }
            calout.write("END:VCALENDAR");
            calout.close();
        }
        if (contacts.size() > 0 | students.size() > 0 | teachers.size() > 0) {
        	out.write("<contacts>\r\n");
        	for (int j = 0; j < contacts.size(); j++) {
        		File vcarddir = new File("vcards");
        		if (!vcarddir.exists()) {
        			vcarddir.mkdir();
        		}
        		File card = new File("vcards\\" + contacts.get(j).getEmail() + ".vcf");
        		if (!card.exists()) {
        			FileWriter fstream3 = new FileWriter("vcards\\" + contacts.get(j).getEmail() + ".vcf");
                    BufferedWriter cardout = new BufferedWriter(fstream3);
                    cardout.write("BEGIN:VCARD\r\nVERSION:2.1\r\n");
                    cardout.write("N:" + contacts.get(j).getName() + ";" + contacts.get(j).getForename() + "\r\n");
                    cardout.write("FN:" + contacts.get(j).getForename() + " " + contacts.get(j).getName() + "\r\n");
                    cardout.write("TITLE:other\r\n");
                    cardout.write("EMAIL;PREF;INTERNET:" + contacts.get(j).getEmail() + "\r\n");
                    cardout.write("TEL;WORK;VOICE:" + contacts.get(j).getPhoneNumber() + "\r\n");
                    cardout.write("END:VCARD");
                    cardout.close();
                    card = new File("vcards\\" + contacts.get(j).getEmail() + ".vcf");
        		}
        		File excard = new File("export\\" + card.getName());
        		copyFile(card, excard);
        		out.write("<file type=\"text/x-vcard\">" + contacts.get(j).getEmail() + ".vcf</file>\r\n");
        	}
        	for (int j = 0; j < students.size(); j++) {
        		File card = new File("vcards\\" + students.get(j).getEmail() + ".vcf");
        		if (!card.exists()) {
        			FileWriter fstream3 = new FileWriter("vcards\\" + students.get(j).getEmail() + ".vcf");
                    BufferedWriter cardout = new BufferedWriter(fstream3);
                    cardout.write("BEGIN:VCARD\r\nVERSION:2.1\r\n");
                    cardout.write("N:" + students.get(j).getName() + ";" + students.get(j).getForename() + "\r\n");
                    cardout.write("FN:" + students.get(j).getForename() + " " + students.get(j).getName() + "\r\n");
                    cardout.write("TITLE:student\r\n");
                    cardout.write("EMAIL;PREF;INTERNET:" + students.get(j).getEmail() + "\r\n");
                    cardout.write("EMAIL;2;INTERNET:" + students.get(j).getAlternativeEmail() + "\r\n");
                    cardout.write("TEL;WORK;VOICE:" + students.get(j).getPhoneNumber() + "\r\n");
                    cardout.write("END:VCARD");
                    cardout.close();
                    card = new File("vcards\\" + students.get(j).getEmail() + ".vcf");
        		}
        		File excard = new File("export\\" + card.getName());
        		copyFile(card, excard);
        		out.write("<file type=\"text/x-vcard\">" + students.get(j).getEmail() + ".vcf</file>\r\n");
        	}
        	for (int j = 0; j < teachers.size(); j++) {
        		File card = new File("vcards\\" + teachers.get(j).getEmail() + ".vcf");
        		if (!card.exists()) {
        			FileWriter fstream3 = new FileWriter("vcards\\" + teachers.get(j).getEmail() + ".vcf");
                    BufferedWriter cardout = new BufferedWriter(fstream3);
                    cardout.write("BEGIN:VCARD\r\nVERSION:2.1\r\n");
                    cardout.write("N:" + teachers.get(j).getName() + ";" + teachers.get(j).getForename() + ";;" + teachers.get(j).getTitle() + "\r\n");
                    cardout.write("FN:" + teachers.get(j).getTitle() + " " + teachers.get(j).getForename() + " " + teachers.get(j).getName() + "\r\n");
                    cardout.write("TITLE:other\r\n");
                    cardout.write("OFFICE:" + teachers.get(j).getOffice() + "\r\n");
                    cardout.write("EMAIL;PREF;INTERNET:" + teachers.get(j).getEmail() + "\r\n");
                    cardout.write("TEL;WORK;VOICE:" + teachers.get(j).getPhoneNumber() + "\r\n");
                    cardout.write("END:VCARD");
                    cardout.close();
                    card = new File("vcards\\" + teachers.get(j).getEmail() + ".vcf");
        		}
        		File excard = new File("export\\" + card.getName());
        		copyFile(card, excard);
        		out.write("<file type=\"text/x-vcard\">" + teachers.get(j).getEmail() + ".vcf</file>\r\n");
        	}
        	out.write("</contacts>\r\n");
        }
        if (lessons.size() > 0 | courses.size() > 0 | projects.size() > 0 | exams.size() > 0 | tasks.size() > 0) {
        	out.write("<extended>\r\n<group5>\r\n");
        	if (lessons.size() != 0) {
        		out.write("<lessons>\n");
	    		for (int i = 0; i < lessons.size(); i++) {
	    			out.write("<lesson>\r\n<start>" + lessons.get(i).getStart() + "</start>\r\n");
	    			out.write("<summary>" + lessons.get(i).getSummary() + "</summary>\r\n");
	    			out.write("<room>" + lessons.get(i).getRoom() + "</room>\r\n");
	    			out.write("<day>" + lessons.get(i).getDayOfWeek() + "</day>\r\n");
	    			out.write("<weeks>" + lessons.get(i).getNumberOfWeeks() + "</weeks>\r\n");
	    			out.write("<course>" + lessons.get(i).getCourseName() + "</course>\r\n");
	    			out.write("</lesson>\r\n");
	    		}
	    		out.write("</lessons>\n");
        	}
        	if (courses.size() != 0) {
        		out.write("<courses>\n");
	        	for (int i = 0; i < courses.size(); i++) {
	        		out.write("<course>\r\n<name>" + courses.get(i).getName() + "</name>\r\n");
	        		out.write("<year>" + courses.get(i).getBeginYear() + "</year>\r\n");
	        		out.write("<semester>" + courses.get(i).getSemester() + "</semester>\r\n</course>\r\n");
	        	}
	        	out.write("</courses>\n");
        	}
        	if (projects.size() != 0) {
        		out.write("<projects>\n");
	        	for (int i = 0; i < projects.size(); i++) {
	        		out.write("<project>\r\n<name>" + projects.get(i).getName() + "</name>\r\n");
	        		out.write("<planning>" + projects.get(i).getPlanning() + "</planning>\r\n");
	        		out.write("<grades>" + projects.get(i).getGrades() + "</grades>\r\n");
	        		out.write("<done>" + projects.get(i).getDone() + "</done>\r\n</project>\r\n");
	        	}
	        	out.write("</projects>\n");
        	}
        	if (exams.size() != 0) {
        		out.write("<exams>\n");
	        	for (int i = 0; i < exams.size(); i++) {
	        		out.write("<exam>\r\n<name>" + exams.get(i).getName() + "</name>\r\n");
	        		out.write("<room>" + exams.get(i).getRoom() + "</room>\r\n");
	        		out.write("<hours>" + exams.get(i).getHours() + "</hours>\r\n");
	        		out.write("<type>" + exams.get(i).getType() + "</type>\r\n");
	        		out.write("<oral>" + exams.get(i).getOral() + "</oral>\r\n");
	        		out.write("<grades>" + exams.get(i).getGrades() + "</grades>\r\n");
	        		out.write("<done>" + exams.get(i).getDone() + "</done>\r\n</exam>\r\n");
	        	}
	        	out.write("</exams>\n");
        	}
        	if (tasks.size() != 0) {
        		out.write("<tasks>\n");
	        	for (int i = 0; i < tasks.size(); i++) {
	        		out.write("<task>\r\n<name>" + tasks.get(i).getName() + "</name>\r\n");
	        		out.write("<grades>" + tasks.get(i).getGrades() + "</grades>\r\n");
	        		out.write("<done>" + tasks.get(i).getDone() + "</done>\r\n</task>\r\n");
	        	}
	        	out.write("</tasks>\n");
        	}
        	out.write("</group5>\r\n</extended>\r\n");
        }
        
        out.write("</export>");
        out.close();
	}
	
	private static void createZip(String path) throws IOException {
		File inFolder=new File("export");
	    File outFolder=new File(path);
	    ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFolder)));
	    BufferedInputStream in = null;
	    byte[] data    = new byte[1000];
	    String files[] = inFolder.list();
	    for (int i=0; i<files.length; i++) {
	    	in = new BufferedInputStream(new FileInputStream(inFolder.getPath() + "/" + files[i]), 1000);                  
	    	out.putNextEntry(new ZipEntry(files[i])); 
	    	int count;
	    	while((count = in.read(data,0,1000)) != -1) {
	    		out.write(data, 0, count);
	        }
	    	out.closeEntry();
	    }
	    out.flush();
	    out.close();
	}
	
	private static void copyFile(File in, File out) throws IOException {
	    FileChannel inChannel = new FileInputStream(in).getChannel();
	    FileChannel outChannel = new FileOutputStream(out).getChannel();
	    try {
	        inChannel.transferTo(0, inChannel.size(), outChannel);
	    } 
	    catch (IOException e) {
	        throw e;
	    }
	    finally {
	        if (inChannel != null) inChannel.close();
	        if (outChannel != null) outChannel.close();
	    }
	}
	
	private static void recursiveDelete(File dirPath) {
	    String[] ls = dirPath.list();
	    for (int idx = 0; idx < ls.length; idx++) {
	    	File file = new File(dirPath, ls[idx]);
	    	if (file.isDirectory())
	        recursiveDelete(file);
	    	file.delete();
	    }
	    dirPath.delete();
	}
	
}
